package dse.messages.singleversion;

import java.util.LinkedList;

import dse.*;
import dse.messages.*;

public class ReleaseLockMessageHandler extends MessageSender implements
		MessageHandler {
	private LockProcessor processor;
	private DataRequest request;
	//private int releaseNum;
	
	public ReleaseLockMessageHandler(Experiment experiment, DataRequest request, LockProcessor processor){
		super(experiment);
		this.request = request;
		this.processor = processor;
		//this.releaseNum = 0;
	}

	@Override
	public boolean acceptMessage(Message message) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void messageInterupted(ExperimentRecorder recorder, Message message,
			double time) {
		// TODO Auto-generated method stub
		//recorder.debug(this, "msgIntrpt: " + message, time);
		//lockProcessor.releaseLock(message.to(), recorder, time);
	}

	@Override
	public void messageReceived(ExperimentRecorder recorder, Message message,
			double time) {
		// TODO Auto-generated method stub
		recorder.debug(this, "msgRcvd: " + message, time);
		if (message.messageType() != MessageType.ReleaseLock) {
			recorder.warn(
					"ReleaseLockMessageHandler recieved " + 
					message.messageType() + " message."
					);
			return;
		}
		//message.to().setSequence(Math.max(message.to().getSequence()+1, message.from().getSequence()));
		//lockProcessor.releaseLock(message.to(), recorder, time);
		Node leader = message.to();
		request.setReleaseNumber(request.getReleaseNumber()+1);
		if((request.getType()==DataRequest.READ && request.getReleaseNumber()>=1)||(request.getType()==DataRequest.WRITE && request.getReleaseNumber()>=request.getLockNumber())){
			leader.getGrantedRequestList(request.getDataID()).remove(request);
			while(leader.getQueuedRequestList(request.getDataID())!=null && leader.getQueuedRequestList(request.getDataID()).size()>0 && leader.canLock(request.getDataID(), leader.getQueuedRequestList(request.getDataID()).last())){
				DataRequest dr = leader.getQueuedRequestList(request.getDataID()).pollLast();
				leader.addGrantedRequest(request.getDataID(), dr);
				dr.setGranted(true);
				Message m = super.createRequestLockResponseMessage(leader, experiment.network().lookupNode(dr.getClientID()), dr, true, message.purpose(), processor);
				//recorder.debug(this, "new msg: " + m, currentTime);
				experiment.messageQueue().enqueueMessage(m, time);
				
				LinkedList<Node> followers = processor.getFollowers();
				for(Node n : followers){
					Message m2 = super.createRequestLockResponseMessage(leader, n, dr, dr.isGranted(), message.purpose(), processor);
					//recorder.debug(this, "new msg: " + m, currentTime);
					experiment.messageQueue().enqueueMessage(m2, time);				
				}
			}
		}
	}

}
